.globl dot

.text
# =======================================================
# FUNCTION: Dot product of 2 int vectors
# Arguments:
#   a0 (int*) is the pointer to the start of v0
#   a1 (int*) is the pointer to the start of v1
#   a2 (int)  is the length of the vectors
#   a3 (int)  is the stride of v0
#   a4 (int)  is the stride of v1
# Returns:
#   a0 (int)  is the dot product of v0 and v1
#
# If the length of the vector is less than 1, 
# this function exits with error code 5.
# If the stride of either vector is less than 1,
# this function exits with error code 6.
# =======================================================
dot:
    # Prologue
    addi sp, sp, -24
    sw ra, 0(sp)
    sw s0, 4(sp)
    sw s1, 8(sp)
    sw s2, 12(sp)
    sw s3, 16(sp)
    sw s4, 20(sp)

    # initial
    add s4, x0, x0

    # if a2 >= 1, goto stride_judge
    addi s0, x0, 1
    bge a2, s0, stride_judge
    # call exit2, status code = 5
    addi a1, x0, 5
    jal ra, exit2

stride_judge:
    slt s1, a3, s0
    slt s2, a4, s0
    or s0, s1, s2
    beq s0, x0, loop_start
    # call exit2, status code = 6
    addi a1, x0, 6
    jal ra, exit2

loop_start:
    # if s0 == length, goto loop_end
    beq s0, a2, loop_end
    slli s1, s0, 2
    # increase = strides * 4 bytes
    mul s2, s1, a3
    mul s3, s1, a4
    add s2, s2, a0
    add s3, s3, a1
    lw s2, 0(s2)
    lw s3, 0(s3)
    mul s2, s2, s3 # s2 = a_i * b_i
    add s4, s4, s2
    addi s0, s0, 1 # s0++
    j loop_start

loop_end:
    add a0, s4, x0

    # Epilogue
    lw ra, 0(sp)
    lw s0, 4(sp)
    lw s1, 8(sp)
    lw s2, 12(sp)
    lw s3, 16(sp)
    lw s4, 20(sp)
    addi sp, sp, 24

    ret
